package com.wkbb.basic.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.wkbb.basic.config.BasicConfig;
import com.wkbb.basic.feign.DoorFeignService;
import com.wkbb.basic.feign.TcCloudFeignService;
import com.wkbb.basic.mapper.DeviceInfoMapper;
import com.wkbb.basic.mapper.EmployeeMapper;
import com.wkbb.basic.model.Employee;
import com.wkbb.basic.model.Family;
import com.wkbb.basic.service.*;
import com.wkbb.common.business.BasicBusiness;
import com.wkbb.common.constants.XmppCommand;
//import com.wkbb.basic.vo.ValidVisitorDeviceUserVo;
import com.wkbb.common.dto.basic.MQTTMessageDto;
import com.wkbb.common.enums.RoleTypeEnum;
import com.wkbb.common.redis.RedisTemplateUtil;
import com.wkbb.common.utils.Base64Util;
import com.wkbb.common.utils.HttpClientUtil;
import com.wkbb.common.utils.StringUtil;
//import com.wkbb.common.vo.DeviceUserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @author Lilin
 */
@Service
@Slf4j
public class XmppServiceImpl implements XmppService {

    @Autowired
    private UserService userService;

    @Autowired
    private DeviceInfoMapper deviceInfoMapper;

    @Autowired
    private BasicConfig basicConfig;

    @Autowired
    private DoorFeignService doorFeignService;

    @Autowired
    private FamilyService familyService;

    @Autowired
    private EmployeeMapper employeeMapper;

    @Autowired
    private RedisTemplateUtil redisTemplateUtil;

    @Autowired
    private TcCloudFeignService tcCloudFeignService;

    private void sendXmppInOrg(Long command, Long orgId, String json) {
        String deviceCodes = deviceInfoMapper.getDeviceCodeListByOrg(orgId);
        sendXmppToDevices(command, deviceCodes, json);
    }

    private void sendXmppToDevices(Long command, String deviceCodes, String json) {
        if (StringUtil.isEmptyIgnoreBlank(deviceCodes)) {
            log.info("【xmpp】发送XMPP指令: deviceCodes 为null，退出！！！,command：{},json:{}", command, json);
        }
        String[] deviceCodesArray = deviceCodes.split(",");

        List<String> mqttDeviceList = new ArrayList<String>();
        List<String> xmppDeviceList = new ArrayList<String>();

        //判断哪些设备走mqtt协议，哪些协议走xmpp协议
        for (String deviceCode : deviceCodesArray) {
            log.info("【mqtt】 判断哪些设备走mqtt协议，哪些协议走xmpp协议  deviceCode:{}", deviceCode);
            Object obj = redisTemplateUtil.get(BasicBusiness.getDeviceProtocalRedisKey(deviceCode));
            if (obj != null) {
                mqttDeviceList.add(deviceCode);
            } else {
                xmppDeviceList.add(deviceCode);
            }
        }

        try {
            if (!mqttDeviceList.isEmpty()) {
                MQTTMessageDto mqttMessageDto = new MQTTMessageDto();
                mqttMessageDto.setCommand(command);
                mqttMessageDto.setJsonMessage(Base64Util.encodeStr(json));
                log.info("【mqtt】发送mqtt指令:command:{}  ===  json:{}", command, json);
                tcCloudFeignService.sendMqttMessageToDevice(mqttMessageDto, StringUtils.join(mqttDeviceList.toArray(), ","));
            }
        } catch (Exception e) {
            log.info("【mqtt】发送mqtt指令:command:{}  ===  json:{},失败，e:{}", command, json, e.getMessage());
        }

        try {
            if (!xmppDeviceList.isEmpty()) {
                HashMap<String, String> params = new HashMap<>(3);
                params.put("iCMD", command.toString());
                if (!StringUtils.isEmpty(json)) {
                    params.put("sJson", Base64Util.encodeStr(json));
                }
                params.put("DeivceIDs", StringUtils.join(xmppDeviceList.toArray(), ","));

                log.info("【xmpp】发送XMPP指令:server:{}  ===  content:{}", basicConfig.getXmppServer(), params.toString());
                HttpClientUtil.doPost(basicConfig.getXmppServer(), params);
            }
        } catch (Exception e) {
            log.info("【xmpp】发送XMPP指令:server:{}  ===  content:{},失败，e:{}", command, json, e.getMessage());
        }
    }

    @Override
    public void sendXmpp(Long command, Long orgId, String deviceCodes) {
        sendXmpp(command, orgId, deviceCodes, null);
    }

    @Override
    public void sendXmpp(Long command, Long orgId, String deviceCodes, String json) {
        if (orgId != null) {
            sendXmppInOrg(command, orgId, json);
        } else {
            sendXmppToDevices(command, deviceCodes, json);
        }
    }

    @Override
    public void reloadAllUser(Long orgId, String deviceCodes) {
        log.info("【xmpp】重载所有用户信息，command:{},orgId:{},deviceCodes:{}", XmppCommand.INIT_ALL, orgId, deviceCodes);
        sendXmpp(XmppCommand.INIT_ALL, orgId, deviceCodes);
    }

//    @Override
//    public void updatePerson(Long orgId, String deviceCodes, Boolean delete, DeviceUserVo user) {
//        JSONObject object = new JSONObject();
//        object.put("delete", delete);
//        object.put("user", user);
//
//        log.info("【xmpp】更新单个用户信息，command:{},orgId:{},deviceCodes:{},data:{}", XmppCommand.UPDATE_PERSON, orgId, deviceCodes, object.toString());
//        sendXmpp(XmppCommand.UPDATE_PERSON, orgId, deviceCodes, object.toString());
//    }

    @Override
    public void restart(Long orgId, String deviceCodes) {
        log.info("【xmpp】重启考勤软件，command:{},orgId:{},deviceCodes:{}", XmppCommand.RESTART, orgId, deviceCodes);
        sendXmpp(XmppCommand.RESTART, orgId, deviceCodes);
    }

    @Override
    public void reboot(Long orgId, String deviceCodes) {
        log.info("【xmpp】重启考勤机，command:{},orgId:{},deviceCodes:{}", XmppCommand.REBOOT, orgId, deviceCodes);
        sendXmpp(XmppCommand.REBOOT, orgId, deviceCodes);
    }

    @Override
    public void upLogs(Long orgId, String deviceCodes, String date) {
        JSONObject object = new JSONObject();
        object.put("date", date);

        log.info("【xmpp】拉取设备日志，command:{},orgId:{},deviceCodes:{},data:{}", XmppCommand.UPLOAD_LOG, orgId, deviceCodes, object.toString());
        sendXmpp(XmppCommand.UPLOAD_LOG, orgId, deviceCodes, object.toString());
    }

    @Override
    public void online(Long orgId, String deviceCodes) {
        log.info("【xmpp】检查设备XMPP连接情况，command:{},orgId:{},deviceCodes:{}", XmppCommand.ONLINE, orgId, deviceCodes);
        sendXmpp(XmppCommand.ONLINE, orgId, deviceCodes);
    }

    @Override
    public void setSimilar(Long orgId, String deviceCodes, Integer similar) {
        JSONObject object = new JSONObject();
        object.put("similar", similar);

        log.info("【xmpp】设置相似度，command:{},orgId:{},deviceCodes:{},data:{}", XmppCommand.FACE_SIMILAR, orgId, deviceCodes, object.toString());
        sendXmpp(XmppCommand.FACE_SIMILAR, orgId, deviceCodes, object.toString());
    }

    @Override
    public void setLevel(Long orgId, String deviceCodes, Integer level) {
        JSONObject object = new JSONObject();
        object.put("level", level);

        log.info("【xmpp】设置识别距离，command:{},orgId:{},deviceCodes:{},data:{}", XmppCommand.SET_LEVEL, orgId, deviceCodes, object.toString());
        sendXmpp(XmppCommand.SET_LEVEL, orgId, deviceCodes, object.toString());
    }

    @Override
    public void setDoorEnable(Long orgId, String deviceCodes, Integer enable) {
        if (enable == null) {
            return;
        }
        JSONObject object = new JSONObject();
        object.put("enable", enable);

        log.info("【xmpp】设置是否强制开门，command:{},orgId:{},deviceCodes:{},data:{}", XmppCommand.DOOR_ENABLE, orgId, deviceCodes, object.toString());
        sendXmpp(XmppCommand.DOOR_ENABLE, orgId, deviceCodes, object.toString());
    }

    @Override
    public void clearCache(Long orgId, String deviceCodes) {
        log.info("【xmpp】清除设备数据，command:{},orgId:{},deviceCodes:{}", XmppCommand.CLEAR_CACHE, orgId, deviceCodes);
        sendXmpp(XmppCommand.CLEAR_CACHE, orgId, deviceCodes);
    }

    @Override
    public void clearLog(Long orgId, String deviceCodes) {
        log.info("【xmpp】清除设备非Crash日志，command:{},orgId:{},deviceCodes:{}", XmppCommand.CLEAR_LOG, orgId, deviceCodes);
        sendXmpp(XmppCommand.CLEAR_LOG, orgId, deviceCodes);
    }

    @Override
    public void clearLogScale(Long orgId, String deviceCodes) {
        log.info("【xmpp】清除老旧日志，直到日志总大小小于1024M，command:{},orgId:{},deviceCodes:{}", XmppCommand.CLEAR_LOG_SCALE, orgId, deviceCodes);
        sendXmpp(XmppCommand.CLEAR_LOG_SCALE, orgId, deviceCodes);
    }

    @Override
    public void assistConnect(Long orgId, String deviceCodes) {
        log.info("【xmpp】检查辅助程序和主程序之间的连接，command:{},orgId:{},deviceCodes:{}", XmppCommand.ASSIST_CONNECT, orgId, deviceCodes);
        sendXmpp(XmppCommand.ASSIST_CONNECT, orgId, deviceCodes);
    }

    @Override
    public void updateCheck(Long orgId, String deviceCodes) {
        log.info("【xmpp】升级检测，command:{},orgId:{},deviceCodes:{}", XmppCommand.UPDATE_CHECK, orgId, deviceCodes);
        sendXmpp(XmppCommand.UPDATE_CHECK, orgId, deviceCodes);
    }

    @Override
    public void configUpdate(Long orgId, String deviceCodes) {
        JSONObject object = new JSONObject();

        log.info("【xmpp】通知设备更新配置信息并上报，command:{}，orgId:{},deviceCodes:{},data:{}", XmppCommand.CONFIG_UPDATE, orgId, deviceCodes, object.toString());
        sendXmpp(XmppCommand.CONFIG_UPDATE, orgId, deviceCodes, object.toString());
    }

    @Override
    public void updateInfrared(Long orgId, String deviceCodes, Boolean infraredFlag, BigDecimal infraredValue, BigDecimal infraredTemperatureCompensation) {
        JSONObject object = new JSONObject();
        object.put("infraredFlag", infraredFlag);
        object.put("infraredValue", infraredValue);
        object.put("infraredTemperatureCompensation", infraredTemperatureCompensation);

        log.info("【xmpp】设备配置信息，command:{},orgId:{},deviceCodes:{},data:{}", XmppCommand.UPDATE_INFRARED_REP, orgId, deviceCodes, object.toString());
        sendXmpp(XmppCommand.UPDATE_INFRARED_REP, orgId, deviceCodes, object.toString());
    }

    @Override
    public void updateStudentMapFamily(Long id, Long orgId, Long userId, Long studentUserId, Integer relationType, boolean delete) {
        JSONObject object = new JSONObject();
        object.put("id", id);
        object.put("familyUserId", userId);
        object.put("studentUserId", studentUserId);
        object.put("relationType", relationType);
        object.put("delete", delete);

        log.info("【xmpp】更新学生家长关系，command:{},orgId:{},data:{}", XmppCommand.UPDATE_STUDENT_MAP_FAMILY, orgId, object.toString());
        sendXmpp(XmppCommand.UPDATE_STUDENT_MAP_FAMILY, orgId, null, object.toString());
    }

//    @Override
//    public void xmppUpdatePerson(Long orgId, Long userId, Short roleType, Date date) {
//        List<DeviceUserVo> user = userService.getUserByDeviceOrg(orgId, userId, roleType == null ? null : roleType.toString(), date);
//
//        log.info("----------本次XMPP同步的用戶----------size:{}", user.size());
//        if (!CollectionUtils.isEmpty(user)) {
//            //还有别的身份，更新
//            user.forEach((e) -> {
//                updatePerson(orgId, null, false, e);
//            });
//        } else {
//            //无其他身份，直接删除
//            DeviceUserVo delUser = new DeviceUserVo();
//            delUser.setId(userId);
//            updatePerson(orgId, null, true, delUser);
//        }
//    }

    @Override
    @Async
    public void xmppUpdateWebankSignTicket(Long orgId, String signTicket) {
        JSONObject object = new JSONObject();
        object.put("signTicket", signTicket);

        log.info("【xmpp】更新webank signticket，command:{},orgId:{},data:{}", XmppCommand.UPDATE_WEBANK_SIGN_TICKET, orgId, object.toString());
        sendXmpp(XmppCommand.UPDATE_WEBANK_SIGN_TICKET, orgId, null, object.toString());
    }

    @Override
    public void xmppUpdatePersonByDate(Long orgId, Date date, int roleType) {
        log.info("----------处理当前学校用户信息到XMPP开始----------orgId:{}", orgId);

        if (roleType == RoleTypeEnum.STUDENT.getValue()) {
            //xmpp推送学生XMPP数据
            xmppUpdatePerson(orgId, null, (short) RoleTypeEnum.STUDENT.getValue(), date);
            //xmpp推送家长XMPP数据
            xmppUpdatePerson(orgId, null, (short) RoleTypeEnum.FAMILY.getValue(), date);

            //查询家长和学生关系
            List<Family> familyListByUpdateTime = familyService.getFamilyListByUpdateTime(orgId, date);

            if (!CollectionUtils.isEmpty(familyListByUpdateTime)) {
                familyListByUpdateTime.forEach((e) -> {
                    log.info("xmpp推送学生家长关系.....start，orgId:{},userId:{}", orgId, e.getUserId());
                    updateStudentMapFamily(e.getId(), orgId, e.getUserId(), e.getStudentUserId(), e.getRelationType(), false);
                    log.info("xmpp推送学生家长关系完成.....start，orgId:{},userId:{}", orgId, e.getUserId());

                    log.info("进入同步学生用户信息到door服务.....start，orgId:{},userId:{},roleType:{}", orgId, e.getStudentUserId(), RoleTypeEnum.STUDENT.getValue());
                    //暂停1秒等待用户数据提交
                    doorFeignService.synUserToDoor(orgId, e.getStudentUserId(), RoleTypeEnum.STUDENT.getValue(), null);
                    log.info("同步学生用户信息到door服务.....end");

                    log.info("进入同步家长用户信息到door服务.....start，orgId:{},userId:{},roleType:{}", orgId, e.getStudentUserId(), RoleTypeEnum.STUDENT.getValue());
                    //暂停1秒等待用户数据提交
                    doorFeignService.synUserToDoor(orgId, e.getUserId(), RoleTypeEnum.FAMILY.getValue(), null);
                    log.info("同步家长用户信息到door服务.....end");
                });
            }
        } else {
            xmppUpdatePerson(orgId, null, (short) RoleTypeEnum.TEACHER.getValue(), date);
            HashMap<String, Object> param = new HashMap<>();
            param.put("orgId", orgId);
            param.put("updateTime", date);
            List<Employee> employeeListByUpdateTime = employeeMapper.getFamilyListByUpdateTime(param);
            if (!CollectionUtils.isEmpty(employeeListByUpdateTime)) {
                employeeListByUpdateTime.forEach((e) -> {
                    log.info("进入同步老师用户信息到door服务.....start，orgId:{},userId:{},roleType:{}", orgId, e.getUserId(), RoleTypeEnum.TEACHER.getValue());
                    //暂停1秒等待用户数据提交
                    doorFeignService.synUserToDoor(orgId, e.getUserId(), RoleTypeEnum.TEACHER.getValue(), null);
                    log.info("同步老师用户信息到door服务.....end");
                });
            }
        }
        log.info("----------处理当前学校的用户信息到XMPP结束----------orgId:{}", orgId);
    }

	@Override
	public void xmppUpdatePerson(Long orgId, Long userId, Short roleType, Date date) {
		// TODO Auto-generated method stub
		
	}

//    @Override
//    @Async
//    public void updateValidVisitorUser(Long orgId, String deviceCodes, ValidVisitorDeviceUserVo ValidVisitorUserDto, boolean delete) {
//        JSONObject object = new JSONObject();
//        object.put("ValidVisitorUserDto", ValidVisitorUserDto);
//        object.put("delete", delete);
//
//        log.info("【xmpp】更新访客信息，command:{},orgId:{},deviceCodes:{},data:{}", XmppCommand.VISITOR_REQUEST, orgId, deviceCodes, object.toString());
//        sendXmpp(XmppCommand.VISITOR_REQUEST, orgId, deviceCodes, object.toString());
//    }


}